﻿namespace Monadic.Tests
{
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System;

    [TestClass]
    public class MonadicTests
    {
        [TestMethod]
        public void Select()
        {
            var result = from x in 7
                         select x;

            Assert.AreEqual(7, result);
        }

        [TestMethod]
        public void SelectTuple()
        {
            var result = from x in Tuple.Create(1, 2)
                         select x.Item1 + x.Item2;

            Assert.AreEqual(3, result);
        }

        static Tuple<string, string> ConferenceInfo()
        {
            return Tuple.Create("IEEE ICCSIT", "Chengdu");
        }

        static Tuple<DateTime, DateTime, DateTime> ConferenceDates()
        {
            return Tuple.Create(new DateTime(2010, 07, 09), new DateTime(2010, 07, 10), new DateTime(2010, 07, 11));
        }

        [TestMethod]
        public void SelectManyTuple()
        {
            DateTime july9th = new DateTime(2010, 07, 09);
            DateTime july11th = new DateTime(2010, 07, 11);
            var result = from info in ConferenceInfo()
                         from dates in ConferenceDates()
                         select new
                         {
                             Name = info.Item1,
                             StartDate = dates.Item1,
                             EndDate = dates.Item3
                         };

            Assert.AreEqual("IEEE ICCSIT", result.Name);
            Assert.AreEqual(july9th, result.StartDate);
            Assert.AreEqual(july11th, result.EndDate);
            
        }

        [TestMethod]
        public void SelectMany()
        {
            var result = from x in 2
                         from y in 3
                         select x + y;

            Assert.AreEqual(5, result);
        }


        [TestMethod]
        public void SelectManyDifferentTypes()
        {
            var result = from x in 2
                         from y in 3.1
                         select x + y;

            Assert.AreEqual(5.1, result);
        }

        [TestMethod]
        public void SelectManyWithEnumerable()
        {
            var nums = new[] { 1, 2, 3 };

            var result = from x in 2.ToEnumerable()
                         from y in nums
                         select x + y;

            Assert.AreEqual(3, result.Count());
        }

        [TestMethod]
        public void WhereValid()
        {
            var result = from x in 7
                         where x != 0
                         select x;

            Assert.AreEqual(7, result);
        }

        [TestMethod]
        public void WhereInvalid()
        {
            var result = from x in 0
                         where x != 0
                         select x;

            Assert.AreEqual(null, result);

            //Ensure it coalesces
            Assert.AreEqual(0, result ?? 0);
        }

        [TestMethod]
        public void OrderBy()
        {
            var result = from x in 7
                         orderby x
                         select x;

            Assert.AreEqual(7, result);
        }

        [TestMethod]
        public void OrderByDescending()
        {
            var result = from x in 7
                         orderby x descending
                         select x;

            Assert.AreEqual(7, result);
        }

        [TestMethod]
        public void Repeat()
        {
            var result = from x in 1.Repeat()
                         select x;
            var sum = result.Take(1000).Sum();

            Assert.AreEqual(1000, sum);
        }
    }
}
